﻿using System;
using System.Data;
using System.Text;

using BizElements.Core.ProviderComponents;

namespace BizElements.Core
{
    /// <summary>Contains database table/view metadata and methods. 
    /// Factory object for related IEntity, EntityCollection and ADO.NET objects.</summary>
    /// <seealso cref="IDbTableConfiguration"/><seealso cref="DbTableExtensions"/>
    public interface IDbTable
    {
        #region Properties - DB metadata.

        /// <summary>Gets catalog information to which the table/view belongs to.</summary>
        ICatalog Catalog { get; }

        /// <summary>Gets table name. </summary>
        string TableName { get; }

        /// <summary>Gets object alias. By default it is equal to the table name. </summary>
        string Alias { get; }

        /// <summary>Gets table fields.</summary>
        DbColumnCollection Columns { get; }

        /// <summary>Gets primary key fields.</summary>
        DbColumnCollection PrimaryKey { get; }

        /// <summary>Gets the relations used by foreign keys. Empty array if no foreign key relations have been defined. </summary>
        DbRelation[] ForeignKeys { get; }

        /// <summary>Gets the value that specifies whether columns' aliases are prefixed and changed whenever the table alias is changed.</summary>
        /// <remarks>Usually columns aliases are prefixed with a table name/alias. This ensures the uniqueness 
        /// of column aliases when selecting two columns with the same name from two different tables.</remarks>
        bool ColumnAliasesArePrefixed { get; }

        /// <summary>Gets the collection of customized information associated with the table.</summary>
        /// <value>A IPropertyCollection with all custom information. <b>null</b> if no custom information is configured.</value>
        /// <remarks>The ExtendedProperties property lets you configure custom information for the table such as DBMS-specific properties.</remarks>
        IPropertyCollection<string> ExtendedProperties { get; }

        /// <summary>Indicates whether the database object is a view.</summary>
        /// <value><b>true</b> if object is a view; otherwise <b>false</b></value>
        bool IsView { get; }

        #endregion

        #region Properties - entities.

        /// <summary>
        /// Gets the names of the properties generated for the parent entities.
        /// </summary>
        string[] ParentEntityProperties { get; }

        #endregion

        #region Methods - DB objects.

        /// <summary>Creates another IDbTable object for the same table/view.</summary>
        /// <param name="cloneAlias">Clone alias.</param>
        /// <returns>Clone.</returns>
        IDbTable Clone(string cloneAlias);

        /// <summary>Creates another IDbTable object for the same table/view.</summary>
        /// <param name="cloneAlias">Clone alias.</param>
        /// <param name="setPrefixedAliases">Specifies whether cloned columns will have prefixed aliases.</param>
        /// <returns>Clone.</returns>
        IDbTable Clone(string cloneAlias, bool setPrefixedAliases);

        /// <summary>Gets tables which reference the current table.</summary>
        /// <returns>Array of tables or empty array if the current table is not referenced by other objects.</returns>
        IDbTable[] GetChildTables();

        /// <summary>Gets relations where current table acts as a parent.</summary>
        /// <returns>Array of relations or empty array if the current table is not referenced by other objects.</returns>
        DbRelation[] GetChildRelations();

        #endregion

        #region Methods - entities.

        /// <summary>Returns a new empty entity that belongs to this table/view. </summary>
        /// <returns>New entity.</returns>
        IEntity NewEntity();

        /// <summary>Returns object that builds entities directly from retrieved data, ie. <see cref="IDataReader"/>.</summary>
        /// <returns>Entity filler.</returns>
        IObjectReader NewEntityReader();

        /// <summary>Gets the full property path for the specified parent entity field.</summary>
        /// <param name="fk">Relation to the parent entity.</param>
        /// <param name="parentColumn">Parent entity field. If null only property name generated for parent entity is returned.</param>
        /// <returns>Parent entity property name followed by dot operator and parent field property name if <b>parentColumn</b> is defined; otherwise only parent entity property name.</returns>
        /// <remarks>Eg. the following code snippet returns "RegionParent.RegionDescription" property path.
        /// <code>
        /// public string GetRegionDescriptionPropertyPath()
        /// {
        ///		TerritoriesMeta territories = new TerritoriesMeta();
        ///		RegionMeta regions = new RegionMeta();
        ///		return territories.GetParentProperty(territories.FK_RegionID, regions.RegionDescription);
        /// }
        /// </code>
        /// </remarks>
        string GetParentProperty(DbRelation fk, IDbColumn parentColumn);

        #endregion
    }    
}